<script lang="ts">
export default {
  name: 'Study7StuDemo1'
}
</script>

<template>
  <h2>生命周期函数-onMounted</h2>
  <div class="note">
    <p>应用场景</p>
    <p>1. 数据初始化加载：在组件挂载后从后端 API 获取数据并展示在页面上。</p>
    <p>2. 注册事件监听器：在组件挂载时注册事件监听器，确保组件销毁时进行清理。</p>
    <p>3. 操作 DOM 元素：需要在 DOM 渲染完成后进行 DOM 操作，如动画、聚焦输入框等。</p>
    <p>4. 执行动画效果: onMounted 确保 DOM 元素已经准备好进行样式和动画的操作。</p>
    <p>5. 第三方库初始化：展示了如何在组件挂载后使用第三方库，如 ECharts，来初始化图表数据。</p>
  </div>

  <hr class="hr-style" />
  <h3>数据初始化加载</h3>
  <div class="group">
    <h4>User List</h4>
    <ul>
      <li v-for="user in users" :key="user.id">{{ user.name }}</li>
    </ul>
  </div>

  <hr class="hr-style" />
  <h3>注册事件监听器</h3>
  <div class="group">
    <button @click="increment">Click me</button>
    <p>You clicked {{ count }} times</p>
    <p>注：按了点击事件后按Enter会每次加2，因为鼠标依然聚焦click按钮</p>
  </div>

  <hr class="hr-style" />
  <h3>操作 DOM 元素</h3>
  <div class="group">
    <input ref="inputEl" placeholder="Focus on me!" />
  </div>

  <hr class="hr-style" />
  <h3>执行动画效果</h3>
  <div class="group">
    <div ref="box" class="box">Hello,world!</div>
  </div>

  <hr class="hr-style" />
  <h3>第三方库初始化</h3>
  <div class="group">
    <div id="chart" style="width: 600px; height: 400px;"></div>
  </div>
</template>

<script setup lang="ts">
import { onMounted, onUnmounted, ref } from 'vue'
import * as echarts from 'echarts'

/**
 * 1. 数据初始化加载
 * 1)场景说明: 该组件在 onMounted 中发起 API 请求，获取用户数据，并在 DOM 中展示。
 */
interface Iuser {
  id: number
  name: string
  username: string
  email: string
  address: {
    street: string
    suite: string
    city: string
    zipcode: string
    geo: {
      lat: string
      lng: string
    }
  }
  phone: string
  website: string
  company: {
    name: string
    catchPhrase: string
    bs: string
  }
}

// 从fecth中获取的数据，定义接收的变量需要声明类型，否则报错
const users = ref<Iuser[]>([])

onMounted(async () => {
  // fetch 是一个用于发起网络请求的 API，广泛用于与服务器进行交互；fecth返回的是Promise对象
  const response = await fetch('https://jsonplaceholder.typicode.com/users')
  users.value = await response.json()
})

/**
 * 2. 注册事件监听器
 * 1）场景说明: 该组件在 onMounted 中监听全局 keydown 事件，当按下回车键时会增加 count，并在组件销毁时移除监听器，避免内存泄漏。
 */
const count = ref(0)
const increment = () => {
  count.value++
}

// 按下Enter键，执行每次加一操作
// 要将事件e的类型声明为 KeyboardEvent，因为只有 KeyboardEvent 类型的对象才有 key 属性(声明为Event将报错)
const handleKeydown = (e: KeyboardEvent) => {
  if (e.key === 'Enter') {
    increment()
  }
}

onMounted(() => {
  window.addEventListener('keydown', handleKeydown)
})

onUnmounted(() => {
  window.removeEventListener('keydown', handleKeydown)
})

/**
 * 3. 操作 DOM 元素
 * 1）场景说明: 该组件在 onMounted 时自动聚焦到输入框，确保用户在页面加载完成后能直接输入
 */
// inputEl 的类型为 HTMLInputElement
const inputEl = ref<HTMLInputElement>()
onMounted(() => {
  (inputEl.value as HTMLInputElement).focus()
})

/**
 * 4. 执行动画效果
 * 1）场景说明: 该组件在 onMounted 后执行一个简单的动画，将一个盒子向右移动 100 像素。
 * 2）onMounted 确保 DOM 元素已经准备好进行样式和动画的操作。
 */
const box = ref<HTMLElement>()
onMounted(()=>{
  // 在组件挂载后执行动画效果
  (box.value as HTMLElement).style.transition = 'transform 1s';
  (box.value as HTMLElement).style.transform = 'translateX(1000px)'
})

/**
 * 5. 第三方库初始化
 * 1) echarts 需手动安装, 且手动 import 导入，编译器无法识别
 * 2）场景说明: 该组件使用了第三方库 ECharts，在 onMounted 中初始化图表，并设置了基本的图表选项。onMounted 保证在组件挂载后，ECharts 库可以正确访问 DOM 元素来进行渲染。
 */
onMounted(()=>{
  // 初始化 ECharts 图表
  const chart = echarts.init(document.getElementById('chart'))
  const option = {
    title: {
      text: 'ECharts Example'
    },
    tooltip: {},
    xAxis: {
      data: ['Shirt', 'Cardigan', 'Chiffon', 'Pants', 'Heels', 'Socks']
    },
    yAxis: {},
    series: [{
      name: 'Sales',
      type: 'bar',
      data: [5, 20, 36, 10, 10, 20]
    }]
  }
  chart.setOption(option)
})
</script>

<style scoped>
.box {
  width: 100px;
  height: 100px;
  background-color: lightblue;
}
body {
  padding: 20px;
}
h2 {
  color: red;
}
h3 {
  color: rgb(220, 85, 85);
}
h4 {
  color: skyblue;
}
.hr-style {
  border: 3px solid gold;
  margin: 20px 0;
}
.group {
  border: 4px solid rgb(102, 215, 85);
  margin: 10px;
  padding: 10px;
}
.note {
  margin: 10px;
  padding: 10px;
  border: 3px solid rgb(221, 121, 202);
}
.note p {
  color: rgb(226, 106, 204);
  font-weight: bold;
}
</style>
